// ------------------------------UI界面------------------------------- //
"ui";
importClass(android.view.View);
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
ui.layout(
    <vertical marginTop="{{Math.max(getStatusBarHeight(), 100)}}px">
        <card w="*" h="auto" margin="10 5" cardCornerRadius="2dp" cardElevation="1dp">
            <vertical padding="18 8" h="auto">
                <Switch id="autoService" text="无障碍服务" checked="{{auto.service != null}}" w="*" textStyle="bold" gravity="right|center_vertical" />
                <Switch id="floatyPermission" text="悬浮窗权限" checked="{{floaty.checkPermission()}}" w="*" textStyle="bold" gravity="right|center_vertical" />
                <input w="*" id="code" inputType="number" gravity="right|center_vertical" hint="输入操作授权码" visibility="gone" />
                <horizontal w="*" h="auto">
                    <text textColor="black" textStyle="bold" >输入操作间隔时间(毫秒,1000毫秒=1秒)</text>
                    <input w="*" id="runInterval" inputType="number" gravity="right|center_vertical" text="1000" />
                </horizontal>
                <horizontal w="*" h="auto">
                    <text textColor="black" textStyle="bold" >查找控件等待超时(毫秒,1000毫秒=1秒)</text>
                    <input w="*" id="overTime" inputType="number" gravity="right|center_vertical" text="5000" />
                </horizontal>
                <horizontal w="*" h="auto">
                    <text textColor="black" textStyle="bold" >刷新按钮延迟时间(毫秒,1000毫秒=1秒)</text>
                    <input w="*" id="refreshTime" inputType="number" gravity="right|center_vertical" text="1000" />
                </horizontal>
                <button id='autoFullClaim' text="开始自动认领" />
                <button id='autoSimpleClaim' text="开始自动认领(需已进入认领页面，直接执行刷新操作)" />
                <button id='autoRobSea' text="开始自动抢海" />
            </vertical>
        </card>
    </vertical>
);
// 本地存储
var sp = storages.create("sp");
ui.runInterval.setText(sp.get('runInterval', 1000) + '');
ui.overTime.setText(sp.get('overTime', 5000) + '');
ui.refreshTime.setText(sp.get('refreshTime', 1000) + '');

// 悬浮顶部信息
var topTips = floaty.rawWindow(
    <frame w="*" bg="#cdcdcd" >
        <vertical w="*" gravity="center">
            <text id="time" w="auto" textColor="red" textStyle="bold" textSize="10sp">00:00</text>
            <text id="text" w="auto" textColor="red" textStyle="bold">按音量+号键可退出脚本!</text>
        </vertical>
        <button id='floatExit' gravity="right" text="退出" />
    </frame>
);
topTips.setTouchable(false);
topTips.setPosition(0, -Math.max(getStatusBarHeight(), 100));
topTips.setSize(device.width, Math.max(getStatusBarHeight(), 100));
// 用户勾选无障碍服务的选项时，跳转到页面让用户去开启
ui.autoService.on("check", function (checked) {
    if (checked && auto.service == null) {
        app.startActivity({
            action: "android.settings.ACCESSIBILITY_SETTINGS"
        });
    }
});
// 用户勾选悬浮窗选项时，跳转到页面让用户去开启
ui.floatyPermission.on("check", function (checked) {
    if (checked && !floaty.checkPermission()) {
        floaty.requestPermission();
    }
});
// 当用户回到本界面时，同步开关的状态
ui.emitter.on("resume", function () {
    ui.autoService.checked = auto.service != null;
    ui.floatyPermission.checked = floaty.checkPermission();
});
// ------------------------------UI界面------------------------------- //

// ------------------------------控制台及服务------------------------------- //
// 开启控制台显示
threads.start(() => {
    console.show();
    console.setTitle("日志记录");
    console.setCanInput(false);
    // 需要延迟修改窗体
    sleep(100);
    console.setSize(device.width - 20, device.height / 3);
    console.setPosition(0, Math.max(getStatusBarHeight(), 100));
    // 控制台最小化
    expandConsoleWindow(false);
});
/**
 * 获取控制台窗口对象
 */
function getConsoleWindow() {
    let mConsole = runtime.console;
    let field = mConsole.class.getDeclaredField("mConsoleFloaty");
    field.setAccessible(true);
    let mConsoleFloaty = field.get(mConsole);
    let mConsoleView = mConsoleFloaty.getExpandedView();
    return mConsoleView;
}
/**
 * 展开控制台窗口
 * @param {boolean} expand 
 */
function expandConsoleWindow(expand) {
    let mConsole = runtime.console;
    let field = mConsole.class.getDeclaredField("mFloatyWindow");
    field.setAccessible(true);
    let mFloatyWindow = field.get(mConsole);
    ui.run(() => {
        if (expand) {
            mFloatyWindow.expand();
        } else {
            mFloatyWindow.collapse();
        }
    });
}

/**
 * 开启前台服务保活
 * @param {string} idStr 
 * @param {string} nameStr 
 */
function startKeepAliveService(nameStr, idStr) {
    try {
        idStr = idStr || "";
        let channelId = idStr + ".foreground";
        let channelName = nameStr + "前台运行服务";
        let contentTitle = nameStr + "正在运行中";
        let contentText = "请勿手动移除该通知";
        let ticker = nameStr + "已启动";
        let manager = context.getSystemService(android.app.Service.NOTIFICATION_SERVICE);
        let notification;
        let icon = context.getResources().getIdentifier("ic_3d_rotation_black_48dp", "drawable", "org.autojs.autoxjs.inrt");
        if (device.sdkInt >= 26) {
            let channel = new android.app.NotificationChannel(channelId, channelName, android.app.NotificationManager.IMPORTANCE_DEFAULT);
            channel.enableLights(true);
            channel.setLightColor(0xff0000);
            channel.setShowBadge(false);
            manager.createNotificationChannel(channel);
            notification = new android.app.Notification.Builder(context, channelId).setContentTitle(contentTitle)
                .setContentText(contentText).setWhen(new Date().getTime()).setTicker(ticker)
                .setOngoing(true).setSmallIcon(icon).build();
        } else {
            notification = new android.app.Notification.Builder(context).setContentTitle(contentTitle)
                .setContentText(contentText).setWhen(new Date().getTime()).setTicker(ticker)
                .setSmallIcon(icon).build();
        }
        manager.notify(1, notification);
    } catch (error) {
        showLogInfo("前台保活服务启动失败:" + error, true);
    }
}

/**
 * 停止前台服务保活
 */
function stopKeepAliveService() {
    let manager = context.getSystemService(android.app.Service.NOTIFICATION_SERVICE);
    manager.cancelAll();
}
// ------------------------------控制台及服务------------------------------- //

// ------------------------------全局监听设置------------------------------- //
var timeSec = 0;
var runTimeStr = '00:00';
// 开启定时器保持悬浮窗不被关闭且更新执行时间
setInterval(() => {
    if (runThread != null) {
        // 设置顶部显示执行时间
        timeSec += 1;
        let min = parseInt(timeSec / 60);
        let sec = parseInt(timeSec % 60);
        let minText = min == 0 ? '00' : (min < 10 ? '0' + min : min);
        let secText = sec == 0 ? '00' : (sec < 10 ? '0' + sec : sec);
        runTimeStr = minText + ":" + secText;
        topTips.time.setText(runTimeStr + ' 累计成功:' + accumulatedCount + '次');
        // 每秒执行任务
        secondTimerTask();
    }
}, 1000);
// 屏蔽音量键调节声音
events.setKeyInterceptionEnabled("volume_up", true);
// 启用按键监听
events.observeKey();
// 监听音量键按下
events.onKeyDown("volume_up", () => {
    exitApp();
});

// 点击开始全流程自动认领按钮操作
topTips.floatExit.click(() => {
    exitApp()
});
// ------------------------------全局监听设置------------------------------- //

// ------------------------------通用工具------------------------------- //
// 单toast提示
var _toast_ = toast;
toast = function (message) {
    _toast_(message);
    if (threads.currentThread() == runThread) {
        sleep(2000);
    }
}

/**
 * 显示运行日志信息
 * @param {string} message 
 * @param {boolean} writeLog 
 */
function showLogInfo(message, writeLog) {
    ui.run(() => {
        // toast(message);
        topTips.text.setText(message);
        if (writeLog) {
            console.log(runTimeStr + ' => ' + message);
        }
    });
}

/**
 * 获取状态栏高度
 */
function getStatusBarHeight() {
    let resources = context.getResources();
    let resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
    let height = resources.getDimensionPixelSize(resourceId);
    return height;
}

/**
 * 退出应用
 * @param {string} toast 
 */
function exitApp(toast) {
    try {
        isAutoClaimMode = false;
        isAutoRobSeaMode = false;
        stopKeepAliveService();
        showLogInfo(toast != null ? toast : '停止退出脚本运行!', true);
        expandConsoleWindow(true);
        topTips.close();
        runThread.interrupt();
        runThread = null;
        exit();
    } catch (error) {

    }
}

/**
 * 等待指定文本控件出现
 * @param {string | UiSelector} target 
 * @param {{string, UiObject?}} callback 
 * @param {boolean} findDesc 
 * @param {string} showText 
 * @param {number} waitRunTime 
 */
function waitFindText(target, callback, findDesc, showText, waitRunTime) {
    let textStr = '';
    if (showText != null) {
        textStr = showText;
    } else {
        if (typeof target == 'string') {
            textStr = target;
        }
    }
    waitRunInterval('开始查找<' + textStr + '>控件', waitRunTime);
    let isCallback = false;
    let startFindTime = Date.now();
    while (!isCallback) {
        let widget = null;
        if (typeof target == 'string') {
            widget = text(target).findOnce();
            if (widget == null && findDesc) {
                widget = desc(target).findOnce();
            }
        } else {
            widget = target;
        }
        if (widget != null) {
            isCallback = true;
            showLogInfo('<' + textStr + '>控件查找成功');
            callback(textStr, widget);
            break;
        } else if (Date.now() - startFindTime >= overTime) {
            isCallback = true;
            showLogInfo('查找不到<' + textStr + '>控件，超时失败', true);
            callback(textStr, null);
            break;
        }
    }
}

/**
 * 查找等待点击文本控件
 * @param {string | UiSelector} target 
 * @param {boolean} callback 
 * @param {boolean} findDesc 
 * @param {string} showText 
 * @param {number} waitRunTime 
 */
function findClickText(target, callback, findDesc, showText, waitRunTime) {
    waitFindText(target, (textStr, widget) => {
        clickTargetWidget(widget, callback, textStr);
    }, findDesc, showText, waitRunTime);
}

/**
 * 点击目标控件
 * @param {UiObject} widget 
 * @param {boolean} callback 
 */
function clickTargetWidget(widget, callback, showText) {
    let textStr = '';
    if (showText != null) {
        textStr = showText;
    } else {
        if (widget.text() != null) {
            textStr = widget.text();
        } else if (widget.desc() != null) {
            textStr = widget.desc();
        }
    }
    if (widget != null) {
        if (click(widget.bounds().centerX(), widget.bounds().centerY())) {
            showLogInfo('<' + textStr + '>控件点击成功');
            callback(true);
        } else {
            showLogInfo('<' + textStr + '>控件点击失败', true);
            callback(false);
        }
    } else {
        showLogInfo('控件点击失败', true);
        callback(false);
    }
}

/**
 * 等待执行间隔时间
 * @param {string} text 
 * @param {number} waitRunTime 
 * @param {boolean} writeLog 
 */
function waitRunInterval(text, waitRunTime, writeLog) {
    let sleepTime = waitRunTime != null ? waitRunTime : runInterval;
    if (sleepTime > 0) {
        showLogInfo('延迟' + parseFloat((sleepTime / 1000.0).toFixed(1)) + '秒 ' + (text != null ? text : ''), writeLog);
    } else {
        showLogInfo('不延迟 ' + (text != null ? text : ''), writeLog);
    }
    sleep(sleepTime);
}

/**
 * 开启运行线程
 */
function startRunThread(run) {
    if (auto.service == null) {
        showLogInfo("请开启无障碍服务!");
    } else if (!floaty.checkPermission()) {
        showLogInfo("请开启悬浮窗权限!");
    } else {
        // 开启前台服务保活
        startKeepAliveService('helper', 'haiouhelper');
        getAccumulatedCount(() => {
            runThread = threads.start(run);
        });
    }
}
// ------------------------------通用工具------------------------------- //

// ------------------------------uniCloud网络数据请求------------------------------- //

// uniCloud域名链接
var baseUrl = "https://fc-mp-ef00ef1e-dd5f-4d11-908b-a4dc9999cfed.next.bspapp.com";
// 输入的授权码
var inputCode = null;
// 操作成功统计累计次数
var accumulatedCount = -1;
// 用户授权获得可操作总次数
var totalCount = 0;

/**
 * 获取用户操作成功统计累计次数
 */
function getAccumulatedCount(success) {
    accumulatedCount = 1;
    success();
    // inputCode = ui.code.text();
    // if (inputCode == null || inputCode == '') {
    //     toast('请输入操作授权码');
    //     showLogInfo('请输入操作授权码');
    // } else {
    //     http.get(baseUrl + '/getAccumulatedCount?code=' + inputCode, {}, function (res, err) {
    //         if (err) {
    //             showLogInfo('获取累计次数失败 ' + err, true);
    //         } else {
    //             showLogInfo('获取累计次数成功', true);
    //             let count = parseInt(res.body.string());
    //             if (count != null && count >= 0) {
    //                 accumulatedCount = count;
    //                 success();
    //             } else {
    //                 toast('获取累计次数失败，请检查授权码输入是否正确');
    //                 showLogInfo('获取累计次数失败，请检查授权码输入是否正确', true);
    //             }
    //         }
    //     });
    // }
}

/**
 * 增加操作成功统计累计次数
 */
function incAccumulatedCount(retry) {
    accumulatedCount += 1;
    // if (retry == null || retry) {
    //     http.get(baseUrl + '/incAccumulatedCount?code=' + inputCode, {}, function (res, err) {
    //         if (err) {
    //             showLogInfo('追加累计成功次数失败 ' + err, true);
    //             if (retry == null) {
    //                 showLogInfo('重试追加累计成功次数', true);
    //                 incAccumulatedCount(true);
    //             }
    //         } else {
    //             let count = parseInt(res.body.string());
    //             if (count != null && count >= 0) {
    //                 accumulatedCount = count;
    //                 showLogInfo('成功追加累计次数', true);
    //             } else {
    //                 showLogInfo('重试追加累计成功次数', true);
    //                 incAccumulatedCount(true);
    //             }
    //         }
    //     });
    // }
}
// ------------------------------uniCloud网络数据请求------------------------------- //

// 操作间隔时间
var runInterval = 1000;
// 操作超时时间
var overTime = 5000;
// 刷新按钮延迟时间
var refreshTime = 1000;
// 正在运行的子线程
var runThread = null;
// 是否为自动认领模式
var isAutoClaimMode = false;
// 是否为自动抢海模式
var isAutoRobSeaMode = false;

// 点击开始全流程自动认领按钮操作
ui.autoFullClaim.click(() => {
    isAutoRobSeaMode = false;
    startOpenShop(() => {
        findClickText('全部门店', (success) => {
            if (success) {
                waitRunInterval('等待门店列表加载', 3000);
                findClickText('距离最近', (success) => {
                    if (success) {
                        findClickText('最新创建', (success1) => {
                            isAutoClaimMode = true;
                            waitRunInterval('等待门店列表加载', 3000);
                            startAutoClaim(false);
                        });
                    } else {
                        exitApp('最新创建切换失败，退出脚本运行!');
                    }
                });
            } else {
                exitApp('关注门店切换失败，退出脚本运行!');
            }
        });
    });
});
// 点击开始刷新步骤自动认领按钮操作
ui.autoSimpleClaim.click(() => {
    isAutoRobSeaMode = false;
    startRunThread(() => {
        if (launch('com.meituan.sankuai.seagull')) {
            isAutoClaimMode = true;
            waitRunInterval('启动海鸥，等待工作台界面加载', 1000, true);
            startAutoClaim(true);
        } else {
            exitApp('海鸥启动失败，退出脚本运行!');
        }
    });
});
// 点击开始自动抢海按钮操作
ui.autoRobSea.click(() => {
    isAutoClaimMode = false;
    startOpenShop(() => {
        findClickText('关注门店', (success) => {
            // 定时时间到了再点击抢海模式
            isAutoRobSeaMode = true;
            showLogInfo('启动定时等待操作');
        });
    });
});

/**
 * 每秒执行任务
 */
function secondTimerTask() {
    // 自动抢海模式
    if (isAutoRobSeaMode) {
        let date = new Date();
        if (date.getHours() < 21 && date.getMinutes() <= 58) {
            let hourText = date.getHours() >= 10 ? date.getHours() : ("0" + date.getHours());
            let minText = date.getMinutes() >= 10 ? date.getMinutes() : ("0" + date.getMinutes());
            let secText = date.getSeconds() >= 10 ? date.getSeconds() : ("0" + date.getSeconds());
            topTips.text.setText("定时20:58:00开始执行任务，当前时间 " + hourText + ":" + minText + ":" + secText);
        } else if (date.getHours() == 20 && date.getMinutes() == 58 && date.getSeconds() == 0) {
            showLogInfo("提前进入加载抢海页面数据", true);
            startAutoRobSea(false);
        } else if (date.getHours() == 21 && date.getMinutes() == 0 && date.getSeconds() == 0) {
            showLogInfo("准点开始执行抢海操作", true);
            startAutoRobSea(true);
        }
    }
};

/**
 * 启动并打开门店，先判断各种权限获取情况
 */
function startOpenShop(callback) {
    let inputRunInterval = parseInt(ui.runInterval.text());
    if (inputRunInterval > 0) {
        runInterval = inputRunInterval;
        sp.put("runInterval", inputRunInterval);
    }
    let inputOverTime = parseInt(ui.overTime.text());
    if (inputOverTime > 0) {
        overTime = inputOverTime;
        sp.put("overTime", inputOverTime);
    }
    let inputRefreshTime = parseInt(ui.refreshTime.text());
    if (refreshTime > 0) {
        refreshTime = inputRefreshTime;
        sp.put("refreshTime", inputRefreshTime);
    }
    startRunThread(() => {
        // 启动海鸥
        waitRunInterval('启动海鸥', 1000, true);
        if (launch('com.meituan.sankuai.seagull')) {
            waitRunInterval('点击工作台', 3000);
            findClickText('工作台', (success) => {
                if (success) {
                    waitRunInterval('等待工作台界面加载', 1000);
                    callback();
                } else {
                    exitApp('工作台切换失败，退出脚本运行!');
                }
            });
        } else {
            exitApp('海鸥启动失败，退出脚本运行!');
        }
    });
};

var lastClaimShopCountStr = null;
var lastClaimShopName = null;

/**
 * 开始自动认领
 * @param {boolean} clickRefresh 是否点击刷新按钮
 */
function startAutoClaim(clickRefresh) {
    if (clickRefresh) {
        let shopCountWidget = textStartsWith('门店总数').findOnce();
        if (shopCountWidget != null) {
            clickTargetWidget(className("TextView").clickable(true).depth(15).findOnce(), (success) => {
                if (success) {
                    waitRunInterval('等待门店列表加载', 0);
                    startAutoClaim(false);
                } else {
                    waitRunInterval('重新刷新!');
                    startAutoClaim(true);
                }
            }, '刷新按钮');
        } else {
            showLogInfo('当前非列表页面尝试返回刷新!', true);
            if (back()) startAutoClaim(true);
        }
    } else {
        let shopCountStr = null;
        let shopCountWidget = textStartsWith('门店总数').findOnce();
        if (shopCountWidget != null) shopCountStr = shopCountWidget.text();
        if (shopCountStr == null || shopCountStr == '门店总数: 0') {
            startAutoClaim(false);
            return;
        }
        if (shopCountStr !== lastClaimShopCountStr) {
            lastClaimShopCountStr = shopCountStr;
            waitFindText('未签约', (textStr, widget) => {
                if (widget == null) {
                    waitRunInterval('第一条数据获取失败，重新刷新!', refreshTime);
                    startAutoClaim(true);
                } else {
                    let target = widget;
                    if (target.parent() != null) target = target.parent();
                    if (lastClaimShopName != null && lastClaimShopName != '' && target.findByText(lastClaimShopName)) {
                        waitRunInterval(lastClaimShopName + '已经操作过，重新刷新!', refreshTime);
                        startAutoClaim(true);
                    } else {
                        findClickText(target.findOne(text('收银公海')), (success) => {
                            if (success) {
                                clickTargetWidget(widget, (success1) => {
                                    if (success1) {
                                        lastClaimShopName = className("TextView").depth(20).findOnce().text();
                                        findClickText('认领', (success2) => {
                                            if (success2) {
                                                findClickText('确定', (success3) => {
                                                    if (success3) {
                                                        let widget = textStartsWith('认领成功，剩余').findOnce();
                                                        if (widget != null) {
                                                            showLogInfo(widget.text(), true);
                                                            incAccumulatedCount();
                                                            if (back()) startAutoClaim(true);
                                                        } else {
                                                            showLogInfo('<' + lastClaimShopName + '>认领失败，执行返回', true);
                                                            if (back()) startAutoClaim(true);
                                                        }
                                                    } else {
                                                        showLogInfo('<' + lastClaimShopName + '>门店认领失败! 执行返回', true);
                                                        if (back()) startAutoClaim(true);
                                                    }
                                                }, false, null, 0);
                                            } else {
                                                showLogInfo('<' + lastClaimShopName + '>门店认领失败! 执行返回', true);
                                                if (back()) startAutoClaim(true);
                                            }
                                        }, false, null, 500);
                                    } else {
                                        showLogInfo('第一条收银公海点击失败，重新点击!', true);
                                        startAutoClaim(false);
                                    }
                                }, '第一条收银公海');
                            } else {
                                waitRunInterval('不符合收银公海，重新刷新!', refreshTime);
                                startAutoClaim(true);
                            }
                        }, false, '第一条收银公海');
                    }
                }
            });
        } else {
            waitRunInterval('未新增门店，重新刷新', refreshTime);
            startAutoClaim(true);
        }
    }
};

// 记录自动抢海控件列表
var autoRobSeaList;

/**
 * 开始自动抢海
 * @param {boolean} startRob 是否整点正式开始抢海
 */
function startAutoRobSea(startRob) {
    if (startRob) {
        if (autoRobSeaList != null && autoRobSeaList.length > 0) {
            for (var i = 0; i < autoRobSeaList.length; i++) {
                autoRobSeaList[i].click();
                // 每点击了一个认领按钮后随机延迟100~300毫秒
                let sleepTime = random(100, 300);
                waitRunInterval('点击下一个认领按钮', sleepTime);
            }
        } else {
            exitApp('抢海列表数据获取失败，退出脚本运行!');
        }
    } else {
        findClickText('抢海模式', (success) => {
            if (success) {
                waitRunInterval('等待抢海界面加载', 3000);
                let retryScrollCount = 0;
                let totalScrollCount = 3;
                while (scrollUp() || retryScrollCount < totalScrollCount) {
                    retryScrollCount = retryScrollCount + 1;
                    waitRunInterval('获取列表数据，次数:' + retryScrollCount + '/' + totalScrollCount, 3000);
                }
                waitRunInterval('回滚顶部获取所有认领控件');
                if (scrollDown()) {
                    autoRobSeaList = text('认领').find();
                    if (autoRobSeaList == null || autoRobSeaList.length <= 0) {
                        exitApp('抢海列表数据获取失败，退出脚本运行!');
                    }
                }
            } else {
                exitApp('抢海模式切换失败，退出脚本运行!');
            }
        });
    }
};